import { filter, has, isNumber, isObject, isUndefined, map, max, min } from 'lodash';
import { getPieDimensions } from './preparePieData';

function getAxisTitle(axis) {
  return isObject(axis.title) ? axis.title.text : null;
}

function getAxisScaleType(axis) {
  switch (axis.type) {
    case 'datetime': return 'date';
    case 'logarithmic': return 'log';
    default: return axis.type;
  }
}

function calculateAxisRange(seriesList, minValue, maxValue) {
  if (!isNumber(minValue)) {
    minValue = Math.min(0, min(map(seriesList, series => min(series.y))));
  }
  if (!isNumber(maxValue)) {
    maxValue = max(map(seriesList, series => max(series.y)));
  }
  return [minValue, maxValue];
}

function prepareXAxis(axisOptions, additionalOptions) {
  const axis = {
    title: getAxisTitle(axisOptions),
    type: getAxisScaleType(axisOptions),
    automargin: true,
  };

  if (additionalOptions.sortX && axis.type === 'category') {
    if (additionalOptions.reverseX) {
      axis.categoryorder = 'category descending';
    } else {
      axis.categoryorder = 'category ascending';
    }
  }

  if (!isUndefined(axisOptions.labels)) {
    axis.showticklabels = axisOptions.labels.enabled;
  }

  return axis;
}

function prepareYAxis(axisOptions, additionalOptions, data) {
  const axis = {
    title: getAxisTitle(axisOptions),
    type: getAxisScaleType(axisOptions),
    automargin: true,
  };

  if (isNumber(axisOptions.rangeMin) || isNumber(axisOptions.rangeMax)) {
    axis.range = calculateAxisRange(data, axisOptions.rangeMin, axisOptions.rangeMax);
  }

  return axis;
}

function preparePieLayout(layout, options, data) {
  const hasName = /{{\s*@@name\s*}}/.test(options.textFormat);

  const { cellsInRow, cellWidth, cellHeight, xPadding } = getPieDimensions(data);

  if (hasName) {
    layout.annotations = [];
  } else {
    layout.annotations = filter(map(data, (series, index) => {
      const xPosition = (index % cellsInRow) * cellWidth;
      const yPosition = Math.floor(index / cellsInRow) * cellHeight;
      return {
        x: xPosition + ((cellWidth - xPadding) / 2),
        y: yPosition + cellHeight - 0.015,
        xanchor: 'center',
        yanchor: 'top',
        text: series.name,
        showarrow: false,
      };
    }));
  }

  return layout;
}

function prepareDefaultLayout(layout, options, data) {
  const ySeries = data.filter(s => s.yaxis !== 'y2');
  const y2Series = data.filter(s => s.yaxis === 'y2');

  layout.xaxis = prepareXAxis(options.xAxis, options);

  layout.yaxis = prepareYAxis(options.yAxis[0], options, ySeries);
  if (y2Series.length > 0) {
    layout.yaxis2 = prepareYAxis(options.yAxis[1], options, y2Series);
    layout.yaxis2.overlaying = 'y';
    layout.yaxis2.side = 'right';
  }

  if (options.series.stacking) {
    layout.barmode = 'relative';
  }

  return layout;
}

function prepareBoxLayout(layout, options, data) {
  layout = prepareDefaultLayout(layout, options, data);
  layout.boxmode = 'group';
  layout.boxgroupgap = 0.50;
  return layout;
}

export default function prepareLayout(element, options, data) {
  const layout = {
    margin: { l: 10, r: 10, b: 10, t: 25, pad: 4 },
    width: Math.floor(element.offsetWidth),
    height: Math.floor(element.offsetHeight),
    autosize: true,
    showlegend: has(options, 'legend') ? options.legend.enabled : true,
  };

  switch (options.globalSeriesType) {
    case 'pie': return preparePieLayout(layout, options, data);
    case 'box': return prepareBoxLayout(layout, options, data);
    default: return prepareDefaultLayout(layout, options, data);
  }
}
